﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel;
using Microsoft.Maps.MapControl;
using System.Collections.Generic;

namespace MyFloridaHouse.libSvOpenDistricts.MapTools
{
    public enum enumLassoMode
    {
        Off,
        Click,
        Lasso,
    }

    public class MapLasso
    {

        #region events
        public delegate void LassoDoneHandler();
        
        public event LassoDoneHandler Done;


        protected void RaiseDoneEvent()
        {
            lastLocationCollection = new Location[lassoPolygon.Locations.Count];
            lassoPolygon.Locations.CopyTo(lastLocationCollection, 0);
            if (Done != null)
            {
                Done();
            }
        }

        public void StartListeningForClick()
        {
            myMap.MouseClick += new EventHandler<MapMouseEventArgs>(newMap_MouseClickHandler);
        }

        public void StartListeningForLasso()
        {
            myMap.MouseMove += new MouseEventHandler(newMap_MouseMoveHandler);
            myMap.MouseClick += new EventHandler<MapMouseEventArgs>(newMap_MouseClickHandler);
            myMap.MouseDoubleClick += new EventHandler<MapMouseEventArgs>(newMap_MouseDoubleClickHandler);
        }

        public void StopListening()
        {
            myMap.MouseMove -= new MouseEventHandler(newMap_MouseMoveHandler);
            myMap.MouseClick -= new EventHandler<MapMouseEventArgs>(newMap_MouseClickHandler);
            myMap.MouseDoubleClick -= new EventHandler<MapMouseEventArgs>(newMap_MouseDoubleClickHandler);
        }
        #endregion

        // map items
        Map myMap;
        MapLayer lassoLayer = new MapLayer();
        private MapPolygon lassoPolygon = new MapPolygon();

        // local items
        enumLassoMode lassoMode = enumLassoMode.Off;
        Location[] lastLocationCollection = new Location[0];

        public MapLasso(Map newMap)
        {
            myMap = newMap;
            myMap.Children.Add(lassoLayer);
            InitializePolygon();
        }


        // methods
        private void InitializePolygon()
        {
            // create a new polygon and add it to the map
            lassoPolygon.Opacity = .5;
            lassoPolygon.Stroke = new SolidColorBrush(Colors.Yellow);
            lassoPolygon.StrokeThickness = 3.0;
            lassoPolygon.Fill = new SolidColorBrush(Colors.Yellow);
            lassoPolygon.Visibility = Visibility.Collapsed;
            lassoLayer.Children.Add(lassoPolygon);
        }

        public bool isLassoActive()
        {
            return ((lassoPolygon.Locations.Count == 0) & (lastLocationCollection.Length > 0));
        }

        public void Reset(enumLassoMode iLassoMode)
        {
            lassoMode = iLassoMode;

            // reset everything to starting point
            lassoPolygon.Locations = new LocationCollection();
            lassoPolygon.Visibility = Visibility.Collapsed;
            StopListening();

            if (lassoMode == enumLassoMode.Click)
            {
                StartListeningForClick();
            }
            else if (lassoMode == enumLassoMode.Lasso)
            {
                StartListeningForLasso();
            }
        }



        void newMap_MouseMoveHandler(object sender, MouseEventArgs e)
        {
            Map map = (Map)sender;
            Location location = map.ViewportPointToLocation(e.GetPosition(map));
            UpdateActivePoint(location);
        }

        void newMap_MouseClickHandler(object sender, MapMouseEventArgs e)
        {
            if (lassoMode == enumLassoMode.Click)
            {
                StopListening();
            }

            Map map = (Map)sender;
            Location location = map.ViewportPointToLocation(e.ViewportPoint);
            AddPoint(location);
            if (lassoMode == enumLassoMode.Click)
            {
                Hide();
                RaiseDoneEvent();
            }
        }

        void newMap_MouseDoubleClickHandler(object sender, MapMouseEventArgs e)
        {
            StopListening();
            Map map = (Map)sender;
            Location location = map.ViewportPointToLocation(e.ViewportPoint);
            AddPoint(location);
            RaiseDoneEvent();
        }

        public void AddPoint(Location newPoint)
        {
            if (lassoPolygon.Locations.Count == 0)
            {
                // add the starting point
                lassoPolygon.Locations.Add(newPoint);
                // add the closing point (same as starting point)
                lassoPolygon.Locations.Add(newPoint);
            }
            // add the next to last point (will be replaced with the current mouse location
            lassoPolygon.Locations.Insert(lassoPolygon.Locations.Count - 2, newPoint);
            Show();

        }

        //public void ClearLastPoint()
        //{
        //    // we either have 0 points or 3 or more, never 1 or 2
        //    if (lassoPolygon.Locations.Count == 3)
        //    {
        //        Hide();
        //        lassoPolygon.Locations.Clear();
        //    }
        //    else if (lassoPolygon.Locations.Count > 3)
        //    {
        //        lassoPolygon.Locations.RemoveAt(lassoPolygon.Locations.Count - 3);
        //    }        
        //}

        public void UpdateActivePoint(Location newEndPoint)
        {
            if (lassoPolygon.Locations.Count > 2)
            {
                lassoPolygon.Locations[lassoPolygon.Locations.Count - 2] = newEndPoint;
            }
        }

        public string GetWKT()
        {
            string result = MapWellKnownText.WktFromLocations(lassoPolygon.Locations);
            return result;
        }

        public void Show()
        {
            lassoPolygon.Visibility = Visibility.Visible;
        }

        public void Hide()
        {
            lassoPolygon.Visibility = Visibility.Collapsed;
        }

        public void RedoLastLasso()
        {
            StopListening();
            foreach(var loc in lastLocationCollection)
            {
                lassoPolygon.Locations.Add(loc);
            }
            Show();
            RaiseDoneEvent();
        }
    }
}
